home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / AppsToGo / Kibitz / Offscreen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  12.1 KB  |  392 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        offscreen.c
  5. ** Written by:  Eric Soldan
  6. **
  7. ** Copyright © 1991-1992 Apple Computer, Inc.
  8. ** All rights reserved. */
  9.  
  10.  
  11.  
  12. /*****************************************************************************/
  13.  
  14.  
  15.  
  16. #include "Kibitz.h"                /* Get the Kibitz includes/typedefs, etc.    */
  17. #include "KibitzCommon.h"        /* Get the stuff in common with rez.        */
  18. #include "Kibitz.protos"        /* Get the prototypes for Kibitz.            */
  19.  
  20. #ifndef __ERRORS__
  21. #include "Errors.h"
  22. #endif
  23.  
  24. #ifndef __GWLAYERS__
  25. #include <GWLayers.h>
  26. #endif
  27.  
  28. #ifndef __RESOURCES__
  29. #include <Resources.h>
  30. #endif
  31.  
  32. #ifndef __UTILITIES__
  33. #include <Utilities.h>
  34. #endif
  35.  
  36.  
  37.  
  38. static short        gDepth, gPiece;
  39. static CTabHandle    gCtab;
  40. static Rect            gPieceRect;
  41. static RgnHandle    gColorRgn, gTestRgn;
  42.  
  43.  
  44.  
  45. /*****************************************************************************/
  46.  
  47.  
  48.  
  49. LayerObj            gBoardLayer;
  50. short                gClearSquare;
  51. extern CIconHandle    gPieceCIcon[26];
  52.  
  53. static OSErr    PieceLayerProc(LayerObj theLayer, short message);
  54. static OSErr    BoardLayerProc(LayerObj theLayer, short message);
  55. static void        PlotWithShadow(short x, short y);
  56.  
  57.  
  58.  
  59. /*****************************************************************************/
  60. /*****************************************************************************/
  61.  
  62. #ifdef applec
  63. #pragma segment Offscreen
  64. #endif
  65.  
  66. /*****************************************************************************/
  67. /*****************************************************************************/
  68.  
  69.  
  70.  
  71. OSErr    InitOffscreen(void)
  72. {
  73.     RgnHandle    colorRgn;
  74.     short        depth;
  75.     OSErr        err;
  76.  
  77.     gClearSquare = 0;        /* Regular board imaging as default. */
  78.  
  79.     colorRgn = ScreenDepthRegion(8);
  80.     depth = (EmptyRgn(colorRgn)) ? 1 : 8;
  81.     DisposeRgn(colorRgn);
  82.  
  83.     err = NewLayer(&gBoardLayer, nil, BoardLayerProc, nil, depth, 0);
  84.         /* We create boardLayer at initialization time.  This layer will be
  85.         ** used to image the board off-screen.  Note that the layer has its own
  86.         ** layerProc.  The kLayerInit action doesn't call the default layerInit.
  87.         ** This custom layerProc uses just the size of the above GWorld to
  88.         ** determine the size of the bitmap it creates, so this layer isn't
  89.         ** necessarily the same depth as the above layer.  If there is no above
  90.         ** layer, then this custom layerProc needs to return paramErr for the
  91.         ** kLayerInit message, just as the default LayerProc does. */
  92.  
  93.     return(err);
  94. }
  95.  
  96.  
  97.  
  98. /*****************************************************************************/
  99.  
  100.  
  101.  
  102. void    MoveThePiece(FileRecHndl frHndl, short fromSq, Rect fromRect, Point fromLoc, Point *toLoc)
  103. {
  104.     WindowPtr        window, keepPort;
  105.     LayerObj        windowLayer, pieceLayer;
  106.     short            dx, dy, adx, ady, ticksForMove, tickDiff, update;
  107.     unsigned long    startTick;
  108.     Point            lastLoc, mouseLoc, pt;
  109.  
  110.     lastLoc.h = lastLoc.v = 0x4000;
  111.         /* Make sure that the first position gets updated.  We want a last mouse
  112.         ** location that is different than whatever the user would have clicked. */
  113.  
  114.     keepPort = SetFilePort(frHndl);
  115.     GetPort(&window);
  116.  
  117.     ImageDocument(frHndl, true);
  118.  
  119.     NewLayer(&windowLayer, nil, nil, window, 8, 0);
  120.         /* Create the layer object related to the window.  If NewLayer fails,
  121.         ** windowLayer is set to nil. */
  122.     (*windowLayer)->dstRect = BoardRect();
  123.         /* pieceLayer isn't the same size as the window's portRect.  By setting
  124.         ** windowLayer's dstRect, we change the area that the two layers map
  125.         ** to.  dstRect is set nil by NewLayer, and if it is left nil, then
  126.         ** the portRect is used for mapping.  Since we only want to map into
  127.         ** the window for the board, we set dstRect to just that portion of
  128.         ** the window. */
  129.     gClearSquare = fromSq;
  130.     gPiece       = (*frHndl)->doc.theBoard[fromSq];
  131.     if (gPiece < WK) gPiece += KSIDEPIECE;
  132.     if (gPiece > BK) gPiece -= KSIDEPIECE;
  133.     ImageDocument(frHndl, true);
  134.     gClearSquare = 0;
  135.  
  136.     gTestRgn  = NewRgn();
  137.     gColorRgn = ScreenDepthRegion(8);        /* Screen of 8-bit or greater get color icon. */
  138.     pt.h = pt.v = 0;
  139.     GlobalToLocal(&pt);
  140.     OffsetRgn(gColorRgn, pt.h, pt.v);        /* Localize the area that gets color icons. */
  141.  
  142.     NewLayer(&pieceLayer, windowLayer, PieceLayerProc, nil, 8, 0);
  143.         /* pieceLayer is created, and it maps to the board area of windowLayer.
  144.         ** Note that windowLayer is a parameter for pieceLayer.  If windowLayer
  145.         ** failed to get created, then this call will return a paramErr.  This
  146.         ** is because if you don't state a port, pixmap, or bitmap, the default
  147.         ** layerProc (which PieceLayerProc calls) uses the above layer to
  148.         ** determine the size and depth of an off-screen GWorld it automatically
  149.         ** creates.  If there is also no above layer, then there is nothing that
  150.         ** can be used as a basis for the GWorld, and that results in a paramErr. */
  151.  
  152.     InsertLayer(gBoardLayer, windowLayer, 2);
  153.         /* Connect board layer in as the background layer. */
  154.     InvalLayer(windowLayer, fromRect, false);
  155.         /* On first update, redraw square where piece was picked up. */
  156.  
  157.     if (toLoc->h != 0x4000) {        /* If we have a start and end point, slide the piece. */
  158.         startTick = TickCount();
  159.         dx = adx = toLoc->h - fromLoc.h;
  160.         if (adx < 0) adx = -adx;
  161.         dy = ady = toLoc->v - fromLoc.v;
  162.         if (ady < 0) ady = -ady;
  163.         ticksForMove = (adx + ady) / 3;
  164. #ifdef powerc
  165.         if (ticksForMove > 6)  ticksForMove = 6;    /* The piece slide will take at most half a second. */
  166. #else
  167.         if (ticksForMove > 30) ticksForMove = 30;    /* The piece slide will take at most half a second. */
  168. #endif
  169.     }
  170.  
  171.     for (;;) {
  172.         if (toLoc->h == 0x4000) {        /* If user grabbed the piece, get where the mouse is now. */
  173.             GetMouse(&mouseLoc);
  174.             update = UpdateTime(frHndl, true);
  175.             if (update) DrawTime(frHndl);
  176.             if (update == 2) {
  177.                 if ((*frHndl)->doc.twoPlayer) SendGame(frHndl, kIsMove, nil);
  178.                 AlertIfGameOver(frHndl);
  179.                 lastLoc.h = lastLoc.v = 0x4000;
  180.                 break;
  181.             }
  182.         }
  183.         else {
  184.             tickDiff = TickCount() - startTick;
  185.             if (tickDiff > ticksForMove) tickDiff = ticksForMove;
  186.             mouseLoc.h = fromLoc.h + dx * tickDiff / ticksForMove;
  187.             mouseLoc.v = fromLoc.v + dy * tickDiff / ticksForMove;
  188.                 /* If sliding piece, calculate the new position, based on time. */
  189.         }
  190.         if ((lastLoc.h != mouseLoc.h) || (lastLoc.v != mouseLoc.v)) {
  191.                 /* If new piece position is different than last... */
  192.             lastLoc = mouseLoc;
  193.             gPieceRect = fromRect;
  194.             gPieceRect.right  += 5;            /* Make space for the piece's shadow. */
  195.             gPieceRect.bottom += 5;
  196.             OffsetRect(&gPieceRect, mouseLoc.h - fromLoc.h - 2, mouseLoc.v - fromLoc.v - 2);
  197.                 /* Position the update rect at the new mouse location but offset 2
  198.                 ** up and 2 left.  This offset is so the piece looks like it is
  199.                 ** lifted from the board for the first update. */
  200.             InvalLayer(windowLayer, gPieceRect, true);    /* Mark the area to be updated. */
  201.             UpdateLayer(windowLayer);                    /* DO IT. */
  202.         }
  203.         if (toLoc->h == 0x4000) {        /* If under user control... */
  204.             if (!StillDown()) break;    /* Break if mouse is released. */
  205.         }
  206.         else if (tickDiff == ticksForMove) break;
  207.             /* If piece being slid, break when it gets there. */
  208.     }
  209.  
  210.     DetachLayer(gBoardLayer);
  211.         /* Keep this permanent layer from being disposed of. */
  212.     DisposeThisAndBelowLayers(windowLayer);
  213.         /* Dispose of the layers and associated data. */
  214.     DisposeRgn(gColorRgn);
  215.     DisposeRgn(gTestRgn);
  216.  
  217.     SetPort(keepPort);
  218.     *toLoc = lastLoc;        /* Return where the piece was dropped. */
  219. }
  220.  
  221.  
  222.  
  223. /*****************************************************************************/
  224.  
  225.  
  226.  
  227. static OSErr    PieceLayerProc(LayerObj theLayer, short message)
  228. {
  229.     OSErr    err;
  230.     GrafPtr    thisPort;
  231.  
  232.     err = noErr;
  233.     switch (message) {
  234.         case kLayerInit:
  235.             gCtab = nil;
  236.                 /* We will need a color table if the depth is greater than 1, and
  237.                 ** we succeed in creating the pixMap for the layer.  Assume that
  238.                 ** these conditions won't be met, and initialize the color table
  239.                 ** reference to nil. */
  240.             err = DefaultLayerProc(theLayer, kLayerInit);
  241.             if (!err) {
  242.                 thisPort = (*theLayer)->layerPort;
  243.                 gDepth = 1;
  244.                 if (thisPort->portBits.rowBytes & 0x8000)
  245.                     gDepth = (*(((CGrafPtr)thisPort)->portPixMap))->pixelSize;
  246.                 if (gDepth != 1) gCtab = GetCTable(64 + 8);
  247.                     /* We need a color table for the shadow if depth is greater than 1. */
  248.             }
  249.             break;
  250.         case kLayerDispose:
  251.             err = DefaultLayerProc(theLayer, kLayerDispose);
  252.                 /* Do the standard dispose behavior. */
  253.             if (gCtab) DisposeCTable(gCtab);
  254.                 /* Dispose of the color table for the piece shadow, if we have one. */
  255.             break;
  256.         case kLayerUpdate:
  257.             DefaultLayerProc(theLayer, kLayerUpdate);
  258.             SetLayerWorld(theLayer);
  259.             PlotWithShadow(gPieceRect.left, gPieceRect.top);
  260.                 /* Draw the piece and shadow into the piece layer in the new position. */
  261.             ResetLayerWorld(theLayer);
  262.             break;
  263.         default:
  264.             err = DefaultLayerProc(theLayer, message);
  265.                 /* For future messages, use the default behavior. */
  266.             break;
  267.     }
  268.  
  269.     return(err);
  270. }
  271.  
  272.  
  273.  
  274. /*****************************************************************************/
  275.  
  276.  
  277.  
  278. static OSErr    BoardLayerProc(LayerObj theLayer, short message)
  279. {
  280.     OSErr        err;
  281.     Rect        boardRect;
  282.     GWorldPtr    layerWorld;
  283.     CGrafPtr    keepPort;
  284.     GDHandle    keepGDevice;
  285.  
  286.     switch (message) {
  287.         case kLayerInit:
  288.             boardRect = BoardRect();
  289.             err = NewGWorld(&layerWorld, (*theLayer)->layerDepth, &boardRect, nil, nil, 0);
  290.             if (!err) {        /* If we succeeded at creating the GWorld... */
  291.                 (*theLayer)->layerOwnsPort = true;
  292.                 GetGWorld(&keepPort, &keepGDevice);        /* To get the GDevice. */
  293.                 (*theLayer)->layerPort    = (GrafPtr)layerWorld;
  294.                 (*theLayer)->layerGDevice = keepGDevice;
  295.                 SetLayerWorld(theLayer);
  296.                 SetOrigin(boardRect.left, boardRect.top);
  297.                 EraseRect(&boardRect);
  298.                     /* Pre-clear the bitmap before imaging into it. */
  299.                 ImageBoardLines(1, kBoardHOffset, kBoardVOffset);
  300.                     /* Pre-image the lines dividing the squares. */
  301.                 ResetLayerWorld(theLayer);
  302.             }
  303.             break;
  304.         default:
  305.             err = DefaultLayerProc(theLayer, message);
  306.                 /* Default behavior for everything else. */
  307.             break;
  308.     }
  309.  
  310.     return(err);
  311. }
  312.  
  313.  
  314.  
  315. /*****************************************************************************/
  316.  
  317.  
  318.  
  319. void    PlotWithShadow(short x, short y)
  320. {
  321.     GrafPtr        curPort;
  322.     Handle        shadowHndl;
  323.     short        pieceShadow;
  324.     ResType        iconType;
  325.     Rect        iconRect, destRect;
  326.     char        hstate;
  327.     PixMap        shadowPixMap;
  328.  
  329.     iconType = (gDepth == 1) ? 'ICON' : 'icl8';
  330.     if ((pieceShadow = gPiece) < 0) pieceShadow = -pieceShadow;
  331.     shadowHndl = GetResource(iconType, 400 + pieceShadow);
  332.     hstate = LockHandleHigh(shadowHndl);
  333.  
  334.     SetRect(&iconRect, 0, 0, 32, 32);
  335.     shadowPixMap.baseAddr   = *shadowHndl;
  336.     shadowPixMap.rowBytes   = (iconType == 'ICON') ? 4 : 0x8020;
  337.     shadowPixMap.bounds     = iconRect;
  338.     shadowPixMap.pmVersion  = 0;
  339.     shadowPixMap.packType   = 0;
  340.     shadowPixMap.packSize   = 0;
  341.     shadowPixMap.hRes       = 0x00480000;
  342.     shadowPixMap.vRes       = 0x00480000;
  343.     shadowPixMap.pixelType  = 0;
  344.     shadowPixMap.pixelSize  = 8;
  345.     shadowPixMap.cmpCount   = 1;
  346.     shadowPixMap.cmpSize    = 8;
  347.     shadowPixMap.planeBytes = 0;
  348.     shadowPixMap.pmTable    = gCtab;
  349.     shadowPixMap.pmReserved = 0;
  350.  
  351.     destRect.bottom = (destRect.top  = y + 5) + 32;
  352.     destRect.right  = (destRect.left = x + 5) + 32;
  353.         /* Add 5 to offset the shadow. */
  354.  
  355.     GetPort(&curPort);
  356.     CopyBits((BitMapPtr)&shadowPixMap, &(curPort->portBits), &iconRect, &destRect, srcOr, nil);
  357.     HSetState(shadowHndl, hstate);
  358.  
  359.     if (!gPieceCIcon[gPiece + KING])
  360.         gPieceCIcon[gPiece + KING] = ReadCIcon(gPiece + KING + 257);
  361.     if (!gPieceCIcon[gPiece + KING + 13])
  362.         gPieceCIcon[gPiece + KING + 13] = ReadCIcon(gPiece + KING + 13 + 257);
  363.  
  364.     OffsetRect(&destRect, -5, -5);
  365.         /* 5 was added for the shadow.  This undoes that. */
  366.  
  367.     if (!RectInRgn(&destRect, gColorRgn))        /* If 1-bit, draw b/w icon. */
  368.         DrawCIconByDepth(gPieceCIcon[gPiece + KING], destRect, 1, true);
  369.  
  370.     else {                                    /* Draw some combo of color and b/w icon. */
  371.         RectRgn(gTestRgn, &destRect);
  372.         SectRgn(gColorRgn, gTestRgn, gTestRgn);
  373.         if ((*gTestRgn)->rgnSize == 10) {
  374.             if (EqualRect(&((*gTestRgn)->rgnBBox), &destRect)) {        /* All color. */
  375.                 DrawCIconByDepth(gPieceCIcon[gPiece + KING + 13], destRect, 8, true);
  376.                 return;
  377.             }
  378.         }
  379.         SetClip(gTestRgn);
  380.         DrawCIconByDepth(gPieceCIcon[gPiece + KING + 13], destRect, 8, true);    /* Color part. */
  381.         RectRgn(gTestRgn, &destRect);
  382.         XorRgn(gColorRgn, gTestRgn, gTestRgn);
  383.         SetClip(gTestRgn);
  384.         DrawCIconByDepth(gPieceCIcon[gPiece + KING], destRect, 1, true);        /* b/w part. */
  385.         SetRectRgn(gTestRgn, -32000, -32000, 32000, 32000);
  386.         SetClip(gTestRgn);
  387.     }
  388. }
  389.  
  390.  
  391.  
  392.